The attached patch adds the support that was only stubbed in to be able
authorsmh22@firebug.cl.cam.ac.uk <smh22@firebug.cl.cam.ac.uk>
Tue, 2 Aug 2005 09:31:47 +0000 (09:31 +0000)
committersmh22@firebug.cl.cam.ac.uk <smh22@firebug.cl.cam.ac.uk>
Tue, 2 Aug 2005 09:31:47 +0000 (09:31 +0000)
to support having reading the boot loader config when you're using a
whole disk (eg, file:/root/disk.img,xvda,w) as opposed to just a
partition.

This reads the partition table in the MBR to find the active partition
and then passes that offset down into the filesystem reading code.

Signed-off-by: Jeremy Katz <katzj@redhat.com>
tools/pygrub/setup.py
tools/pygrub/src/fsys/ext2/__init__.py
tools/pygrub/src/fsys/ext2/ext2module.c
tools/pygrub/src/pygrub

index b72ea38857bdfe4ce1da30824e243ab2a963562a..6b32346b065529734b18c288df56cb95e04558de 100644 (file)
@@ -23,7 +23,7 @@ if os.path.exists("/usr/include/reiserfs/reiserfs.h"):
     fsys_pkgs.append("grub.fsys.reiser")
 
 setup(name='pygrub',
-      version='0.2',
+      version='0.3',
       description='Boot loader that looks a lot like grub for Xen',
       author='Jeremy Katz',
       author_email='katzj@redhat.com',
index ff8f7af48ff7705518329026fc605ec0ebd7ead8..4c3fe12c000a13600d855c305e1125ef9989f2c9 100644 (file)
@@ -32,7 +32,7 @@ class Ext2FileSystemType(FileSystemType):
     def open_fs(self, fn, offset = 0):
         if not self.sniff_magic(fn, offset):
             raise ValueError, "Not an ext2 filesystem"
-        return Ext2Fs(fn)
+        return Ext2Fs(fn, offset = offset)
 
 register_fstype(Ext2FileSystemType())
 
index bef4bb6f9f19348f912bd8d2b848661fb2e963f7..7b81d8bab77d0c3f432f241a62ac593ff763f31a 100644 (file)
@@ -208,22 +208,28 @@ static PyObject *
 ext2_fs_open (Ext2Fs *fs, PyObject *args, PyObject *kwargs)
 {
     static char *kwlist[] = { "name", "flags", "superblock", 
-                              "block_size", NULL };
+                              "block_size", "offset", NULL };
     char * name;
-    int flags = 0, superblock = 0, err;
+    int flags = 0, superblock = 0, offset = 0, err;
     unsigned int block_size = 0;
     ext2_filsys efs;
+    char offsetopt[30];
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist, 
-                                     &name, &flags, &superblock, &block_size))
-                                     return NULL;
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", kwlist, 
+                                     &name, &flags, &superblock, 
+                                     &block_size, &offset))
+        return NULL;
 
     if (fs->fs != NULL) {
         PyErr_SetString(PyExc_ValueError, "already have an fs object");
         return NULL;
     }
 
-    err = ext2fs_open(name, flags, superblock, block_size, 
+    if (offset != 0) {
+        snprintf(offsetopt, 29, "offset=%d", offset);
+    }
+
+    err = ext2fs_open2(name, offsetopt, flags, superblock, block_size, 
                       unix_io_manager, &efs);
     if (err) {
         PyErr_SetString(PyExc_ValueError, "unable to open file");
@@ -323,14 +329,15 @@ static PyObject *
 ext2_fs_new(PyObject *o, PyObject *args, PyObject *kwargs) 
 {
     static char *kwlist[] = { "name", "flags", "superblock", 
-                              "block_size", NULL };
+                              "block_size", "offset", NULL };
     char * name;
-    int flags = 0, superblock = 0;
+    int flags = 0, superblock = 0, offset;
     unsigned int block_size = 0;
     Ext2Fs *pfs;
 
-    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iii", kwlist, 
-                                     &name, &flags, &superblock, &block_size))
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iiii", kwlist, 
+                                     &name, &flags, &superblock, &block_size,
+                                     &offset))
         return NULL;
 
     pfs = (Ext2Fs *) PyObject_NEW(Ext2Fs, &Ext2FsType);
@@ -339,8 +346,8 @@ ext2_fs_new(PyObject *o, PyObject *args, PyObject *kwargs)
     pfs->fs = NULL;
 
     if (!ext2_fs_open(pfs, 
-                      Py_BuildValue("siii", name, flags, superblock, block_size),
-                      NULL))
+                      Py_BuildValue("siiii", name, flags, superblock, 
+                                    block_size, offset), NULL))
         return NULL;
 
     return (PyObject *)pfs;
index 545feea54fd9d38fd1588e2134d2d6e4a972bbc1..765f54c71e41e34bae3123dab02af73395caf7d9 100644 (file)
@@ -24,7 +24,7 @@ sys.path = [ '/usr/lib/python' ] + sys.path
 import grub.GrubConf
 import grub.fsys
 
-PYGRUB_VER = 0.02
+PYGRUB_VER = 0.3
 
 
 def draw_window():
@@ -77,24 +77,39 @@ def is_disk_image(file):
     buf = os.read(fd, 512)
     os.close(fd)
 
-    if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaaff):
+    if len(buf) >= 512 and struct.unpack("H", buf[0x1fe: 0x200]) == (0xaa55,):
         return True
     return False
 
+SECTOR_SIZE=512
+def get_active_offset(file):
+    """Find the offset for the start of the first active partition in the
+    disk image file."""
+    fd = os.open(file, os.O_RDONLY)
+    buf = os.read(fd, 512)
+    for poff in (446, 462, 478, 494): # partition offsets
+        # active partition has 0x80 as the first byte
+        if struct.unpack("<c", buf[p:p+1]) == ('\x80',):
+            return struct.unpack("<", buf[p+8:p+12])[0] * SECTOR_SIZE
+    return -1
+
 def get_config(fn):
     if not os.access(fn, os.R_OK):
         raise RuntimeError, "Unable to access %s" %(fn,)
 
     cf = grub.GrubConf.GrubConfigFile()
 
+    offset = 0
     if is_disk_image(fn):
-        raise RuntimeError, "appears to be a full disk image... unable to handle this yet"
+        offset = get_active_offset(fn)
+        if offset == -1:
+            raise RuntimeError, "Unable to find active partition on disk"
 
     # open the image and read the grub config
     fs = None
     for fstype in grub.fsys.fstypes.values():
-        if fstype.sniff_magic(fn):
-            fs = fstype.open_fs(fn)
+        if fstype.sniff_magic(fn, offset):
+            fs = fstype.open_fs(fn, offset)
             break
 
     if fs is not None:
@@ -244,14 +259,17 @@ if __name__ == "__main__":
     if img.initrd:
         print "  initrd: %s" %(img.initrd[1],)
 
+    offset = 0
     if is_disk_image(file):
-        raise RuntimeError, "unable to handle full disk images yet"
+        offset = get_active_offset(fn)
+        if offset == -1:
+            raise RuntimeError, "Unable to find active partition on disk"
 
     # read the kernel and initrd onto the hostfs
     fs = None
     for fstype in grub.fsys.fstypes.values():
-        if fstype.sniff_magic(file):
-            fs = fstype.open_fs(file)
+        if fstype.sniff_magic(file, offset):
+            fs = fstype.open_fs(file, offset)
             break
 
     if fs is None: